/*********************************** (C) COPYRIGHT ******************************
 * address: https://gitee.com/liuniansihuo/multitasks-os
 *
 * Change Logs:
 * Date			Author      	Notes
 * 2018-11-21	LiuHuo			first version
 *
*******************************************************************************/
#include "QueueRing.h"

#define Q_assert_param(Q) 	//do {if((Q == NULL) || (Q->size == 0) ||(Q->buff == NULL)||(Q->type==0)) return;}while(0)

/*
* function:字节拷贝
* param:
	dst:目的地址
	src:源地址
	len:拷贝长度
* return:0
*/
static unsigned short  memset(unsigned char* dst, const unsigned char* src, unsigned short  len)
{
	unsigned short  i;
	for(i=0; i<len; i++)
		*(dst+i) = *(src+i);

    return 0;
}
/*
* function:队列队尾设置偏移，基于当前队尾
* param:
	Q:队列地址
	offset:偏移数
* return:返回设置后的队尾数
*/
unsigned short  SetTail(struct QueRing_s* Q, unsigned short  offset)
{
	unsigned short  i=0;
	Q_assert_param(Q);
	i=QCurrentSize(Q);

	offset = (i<offset) ? i : offset;
	Q->tail = (Q->tail+offset) % Q->size;
	return Q->tail;
}
/*
* function:队列队头设置偏移，基于当前队头
* param:
	Q:队列地址
	offset:偏移数
* return:返回设置后的队头数
*/
unsigned short  SetHeadOffset(struct QueRing_s *Q,unsigned short  offset)
{
	unsigned short  i=0;
	Q_assert_param(Q);
	i=QRemainSize(Q);
	offset = (i<offset) ? i : offset;
	Q->head = (Q->head+offset) % Q->size;
	return Q->head;
}
/*
* function:队列队头设置
* param:
	Q:队列地址
	offset:偏移数
* return:返回设置后的队头数
*/
unsigned short  SetHead(struct QueRing_s *Q,unsigned short  head)
{
	//unsigned short  i=0;
	Q_assert_param(Q);
	Q->head = (head < Q->size) ? head : Q->head;
	return Q->head;
}
/*
* function:获取总缓存中 第index 个元素
* param:
	Q:队列地址
	index:
* return:返回第index 个元素地址
*/
static void* GetDataRandom(struct QueRing_s*Q,unsigned short  index)
{
	Q_assert_param(Q);
	index %= Q->size;
	return (void *)((unsigned int)Q->buff+index*Q->type);
}
/*
* function:获取 第 offset 个元素
* param:
	Q:队列地址
	offset:
* return:返回第 offset 个元素地址
*/
void * GetData(struct QueRing_s*Q,unsigned short  offset)
{
	unsigned short  tail=0;
	Q_assert_param(Q);
	if(offset>=QCurrentSize(Q))
		return 0;

	tail = (Q->tail+offset)%Q->size;
	return GetDataRandom(Q,tail);
}
/*
* function:从队尾获取一个数据，并移动队尾
* param:
	Q:队列地址
* return:返回地址
*/
void * GetDataAdd(struct QueRing_s*Q)
{
	unsigned short  tail=0;
	Q_assert_param(Q);
	if(QEmpty(Q))
		return 0;

	tail = Q->tail;
	Q->tail++;
	Q->tail%= Q->size;
	return GetDataRandom(Q,tail);
}
/*
* function:插入队头一个元素，并移动队头
* param:
	Q:队列地址
	data：插入元素地址
	len:插入元素个数
* return:返回实际插入个数
*/
unsigned short  SetData(struct QueRing_s*Q,void * data,unsigned short  len)
{
	unsigned short  i=0;
	Q_assert_param(Q);
	for(i=0; i<len; i++)
	{
		if(Q->tail == ((Q->head+1)%Q->size))
			break;

		memset((unsigned char*)((unsigned char*)Q->buff + Q->head*Q->type), (unsigned char*)((unsigned char*)data + i*Q->type), Q->type);
		Q->head++;
		Q->head%=Q->size;
	}

	return i;
}
/*
* function:新队列初始化
* param:
	Q:队列地址
	buff：队列缓存
	size:插入元素个数
	type：单个元素大小
* return:
*/
void QueueInit(struct QueRing_s * Q, void * buff, unsigned short  size,unsigned short  type)
 {
 	unsigned short  i=0;
	unsigned int  temp;

	if((Q == 0) || (size == 0) ||(buff == 0)||(type==0))
		return;

	Q->head=0;
	Q->tail=0;
	Q->size=size;
	Q->type = type;
	Q->buff = buff;

	temp=size*type;
	for(i=0; i<temp; i++)
		((unsigned char*)Q->buff)[i]=0;
 }





